﻿using System;
using System.Linq;
using Omu.ValueInjecter;

namespace Icms.Core.Utils
{
    public class StringToByteArray : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            return c.SourceProp.Name == c.TargetProp.Name
                   && c.SourceProp.Type == typeof(string)
                   && c.TargetProp.Type == typeof(byte[])
                   && c.SourceProp.Value != null;
        }

        protected override object SetValue(ConventionInfo c)
        {
            return System.Text.Encoding.Unicode.GetBytes(c.SourceProp.Value.ToString());
        }
    }

    public class ByteArrayToString : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            return c.SourceProp.Name == c.TargetProp.Name &&
                   c.SourceProp.Type == typeof(byte[]) &&
                   c.TargetProp.Type == typeof(string) &&
                   c.SourceProp.Value != null;
        }

        protected override object SetValue(ConventionInfo c)
        {
            return System.Text.Encoding.Unicode.GetString((byte[])c.SourceProp.Value);
        }
    }

    public class NullablesToNormal : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            return c.SourceProp.Name == c.TargetProp.Name &&
                   Nullable.GetUnderlyingType(c.SourceProp.Type) == c.TargetProp.Type;
        }
    }

    public class NormalToNullables : ConventionInjection
    {
        protected override bool Match(ConventionInfo c)
        {
            //ignore int = 0, Guid = empty, and DateTime = to 1/01/0001
            if (c.SourceProp.Type == typeof(DateTime) && (DateTime)c.SourceProp.Value == default(DateTime) ||
            (c.SourceProp.Type == typeof(int) && (int)c.SourceProp.Value == default(int)) ||
            (c.SourceProp.Type == typeof(Guid) && (Guid)c.SourceProp.Value == default(Guid)))
                return false;

            return (c.SourceProp.Name == c.TargetProp.Name &&
                    c.SourceProp.Type == Nullable.GetUnderlyingType(c.TargetProp.Type));
        }
    }

    public class Same : ConventionInjection
    {
        private readonly string[] ignores;

        public Same(params string[] ignores)
        {
            this.ignores = ignores;
        }

        protected override bool Match(ConventionInfo c)
        {
            return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Type == c.TargetProp.Type
                && !ignores.Contains(c.SourceProp.Name);
        }
    }
}
